#include "StdAfx.h"
#include "Board.h"

//===========================================================================
IBoard * CreateBoard( void )
{
    return new Board();
}

//===========================================================================
Board::Board( void )
{
}

//===========================================================================
Board::~Board( void )
{
}

//===========================================================================
void Board::Release( void )
{
    Board::Release( this );
}

//===========================================================================
void Board::Release(
    Board * board
) {
    if( board )
        delete board;
}

//===========================================================================
void Board::Initialize(
    Piece top,
    Piece bottom
) {
    for( unsigned int i = 0; i < ROWS; i++ )
        for( unsigned int j = 0; j < BOARD_SIZE; j++ )
            this->m_board[ i ][ j ] = ( i + j ) % 2
                                    ? top
                                    : Piece::NONE;

    for( unsigned int i = ROWS; i < BOARD_SIZE - ROWS; i++ )
        for( unsigned int j = 0; j < BOARD_SIZE; j++ )
            this->m_board[ i ][ j ] = Piece::NONE;

    for( unsigned int i = BOARD_SIZE - ROWS; i < BOARD_SIZE; i++ )
        for( unsigned int j = 0; j < BOARD_SIZE; j++ )
            this->m_board[ i ][ j ] = ( i + j ) % 2
                                    ? bottom
                                    : Piece::NONE;
}

//===========================================================================
void Board::Draw( void ) const
{
    for( unsigned int i = 0; i < BOARD_SIZE; i++ ) {
        cout << i << "  ";
        
        for( unsigned int j = 0; j < BOARD_SIZE; j++ )
            cout << this->m_board[ i ][ j ].Str() << " ";

        cout << endl;
    }
    
    cout << endl << "   ";
    for( unsigned int i = 0; i < BOARD_SIZE; i++ )
        cout << i << " ";
    cout << endl;
}

//===========================================================================
bool Board::Move(
    const IRoute * route
) {
    if( !route )
        return false;

    unsigned int moves = route->GetMoveCount();
    if( moves < 2 )
        return false;

    Piece piece;
    const Position * from = route->GetAt( 0 );
    if(    !this->GetPiece( from, piece )
        || piece == Piece::NONE )
        return false;

    for( unsigned int i = 1; i < moves; i++ ) {
        auto to = route->GetAt( i );        
        if( !this->IsValidMove( from, to ) )
            return false;
        
        from = to;
    }
    
    cout << endl << "[ MOVES ] : ";
    const Position * position = NULL;
    for( unsigned int i = 0; i < moves - 1; i++ ) {
        position = route->GetAt( i );
        this->SetPiece(
            position,
            Piece::NONE
        );

        cout << "(" << position->x << "," << position->y << ") ";
    }
    
    position = route->GetDestination();
    this->SetPiece(
        route->GetDestination(),
        piece
    );
    cout << "(" << position->x << "," << position->y << ") " << endl;

    return true;
}

//===========================================================================
bool Board::SetPiece(
    const Position * position,
          Piece      piece
) {
    if( !this->IsValidPosition( position ) )
        return false;

    this->m_board[ position->x ][ position->y ] = piece;
    return true;
}

//===========================================================================
bool Board::IsValidMove(
    const Position * from,
    const Position * to
) {
    return this->IsValidPosition( from )
        && this->IsValidPosition( to   )
        && 1 == abs( static_cast< int >( from->x - to->x ) )
        && 1 == abs( static_cast< int >( from->y - to->y ) );
}

//===========================================================================
bool Board::IsValidPosition(
    const Position * position
) const {
    return position
        && position->x < BOARD_SIZE
        && position->y < BOARD_SIZE;
}

//===========================================================================
bool Board::GetPiece(
    const Position * position,
          Piece &    piece
) const {
    if( !this->IsValidPosition( position ) )
        return false;

    piece = this->m_board[ position->x ][ position->y ];    
    return true;
}

//===========================================================================
unsigned int Board::GetSize( void ) const
{
    return BOARD_SIZE;
}